package com.ywk.mapperRegister.core.annRegister;

import com.ywk.mapperRegister.core.DBMapperFactoryBean;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import java.util.HashSet;
import java.util.Set;

/**
 * 扫描注解 @DBMapper动态生成代理的接口 bean
 *
 * @Author zbh
 * @Date 2023/7/19
 */
public class DBMapperRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware, ResourceLoaderAware {

    private Environment environment;

    private ResourceLoader resourceLoader;

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //使用classpath注解扫描器
        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false,
                this.environment) {
            @Override
            protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
                // 作为案例这里先不做判断，全部通过
                return true;
            }
        };
        //设置资源加载器
        scanner.setResourceLoader(this.resourceLoader);
        // 过滤只扫描 DBMapper 注解
        scanner.addIncludeFilter(new AnnotationTypeFilter(DBMapper.class));
        Set<BeanDefinition> beanDefinitions = new HashSet<>();
        //扫描根目录下的所有文件
//        String sourcePath="com.ywk.mapperRegister";
        String str = System.getProperties().getProperty("sun.java.command");//获取启动类全类名
        String sourcePath=str.substring(0,str.lastIndexOf("."));
        Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(sourcePath);
        beanDefinitions.addAll(candidateComponents);
        //根据bean定义进行注册
        registerBeanDefinition(beanDefinitions, registry);
    }

    /**
     * bean注册
     * @param
     * @param registry
     */
    private void registerBeanDefinition(Set<BeanDefinition> beanDefinitions, BeanDefinitionRegistry registry) {
        for (BeanDefinition beanDefinition : beanDefinitions) {
            BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, beanDefinition.getBeanClassName());
            AbstractBeanDefinition definition = (AbstractBeanDefinition) holder.getBeanDefinition();
            //获取 mapper Class
            String beanClassName = definition.getBeanClassName();
            //将definition的类型改为 YwkMapperFactoryBean，自定义的 FactoryBean
            definition.setBeanClass(DBMapperFactoryBean.class);
            //设置 bean实例化时使用的构造方法，传入对应参数
            definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName);
            //注册
            BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
        }
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }


}
